package com.qn.utils;

import com.qn.entity.Sendnumbers;
import com.qn.common.ServerSenderProp;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.mail.MailProperties;
import org.springframework.mail.MailAuthenticationException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.annotation.Resource;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.Map;

/**
 * @author 源源大魔王
 * @date 2021/9/24 11:58
 * @description 邮件工具类
 */
@Component
@EnableAsync
@Slf4j
public class MailUtils {
    /**
     * 发送邮件的模板对象
     */
    @Resource
    private JavaMailSenderImpl javaMailSender;
    /**
     * 电子邮件支持的配置属性
     */
    @Resource
    private MailProperties mailProperties;

    @Resource
    private ServerSenderProp senderProp;

    //初始化配置
    static {
        //开启系统网络IP协议ipv4
        System.setProperty("java.net.preferIPv4Stack", "true");
    }

    /**
     * 模板引擎
     */
    @Resource
    TemplateEngine templateEngine;

    /**
     * <h1>邮件程序发送</h1>
     *
     * @param receiveEmail 收件人邮箱
     * @param mailTitle    邮件标题
     * @param mailContent  邮件内容
     * @return 是否发送成功
     * @date 2021/10/17 1:40
     */
    public synchronized Boolean sendMail(Sendnumbers sender, String receiveEmail, String mailTitle, String mailContent) {
        //捕获异常,出现异常就返回false代表失败
        try {
            javaMailSender.setHost("smtp." + sender.getEmailnumber().substring(sender.getEmailnumber().indexOf('@') + 1));
            javaMailSender.setUsername(sender.getEmailnumber());
            javaMailSender.setPassword(sender.getEmailpwd());
            MimeMessage message = javaMailSender.createMimeMessage();
            //设置发件人必须是这个账号
            message.setFrom(new InternetAddress(sender.getEmailnumber()));
            //设置收件人
            message.setRecipient(Message.RecipientType.TO, new InternetAddress(receiveEmail));
            message.setSubject(mailTitle);
            //设置内容
            message.setContent(mailContent, "text/html;charset=UTF-8");
            //设置发送时间
            message.setSentDate(new Date());
            //保存邮件
            message.saveChanges();
            javaMailSender.send(message);
        } catch (AuthenticationFailedException | MailAuthenticationException e) {
            log.error("----*发件人认证失败*----");
            log.error("原因:", e);
            return false;
        } catch (SendFailedException e) {
            log.error("----*发送时异常*----");
            log.error("原因:", e);
            return false;
        } catch (MessagingException e) {
            log.error("----*邮件异常*----");
            log.error("原因:", e);
            return false;
        } catch (Exception e) {
            log.error("----*程序发送时出现了其他异常*----");
            log.error("原因:", e);
            return false;
        }
        return true;
    }

    /**
     * <h1>服务器发送</h1>
     *
     * @param receiveEmail 收件人邮箱
     * @param mailTitle    邮件标题
     * @param mailContent  邮件内容
     * @return 是否发送成功
     * @date 2021/10/17 1:40
     */
    public Boolean serverSend(String receiveEmail, String mailTitle, String mailContent) {
        try {
            //shell命令拼接,否则指令无法识别,导致执行失败 其中 root@localhost.localdomain为发件人邮件,这个要跟搭建的邮件服务配置相同才能发送
            String[] cmd = new String[]{"sendEmail", "-f", senderProp.getEmail(), "-t", receiveEmail, "-u", mailTitle, "-xu", senderProp.getEmail(), "-xp", senderProp.getPassword(), "-m", mailContent, "-a", "", "-o", "message-header=GB2312", "-o", "message-content-type=html", "-o", "message-charset=utf8", "-o", "tls=no"};
            Runtime.getRuntime().exec(cmd).getInputStream();
        } catch (IOException e) {
            log.error("shell执行IO异常:" + e.getMessage());
            return false;
        } catch (Exception e) {
            log.error("shell执行时出现其他异常:" + e.getMessage());
            return false;
        }
        return true;
    }


    /**
     * 发送简单邮件
     *
     * @param toAccount
     * @param subject
     * @param content
     */
    @Async
    public void sendSimpleMail(String toAccount, String subject, String content) {
        try {
            SimpleMailMessage message = new SimpleMailMessage();
            //设置发件人
            message.setFrom(mailProperties.getUsername());
            //设置收件人，收件人可以是一个数组，也可以是一个字符串
            message.setTo(toAccount);
            //设置主题
            message.setSubject(subject);
            //设置发送内容
            message.setText(content);
            //设置发送日期
            message.setSentDate(new Date());
            //发送邮件
            javaMailSender.send(message);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送带附件的邮件
     */
    public void sendMailWithFile() {
        try {
            //发送带附件的邮件使用的类是 mimeMessage
            MimeMessage msg = javaMailSender.createMimeMessage();
            //创建MimeMessage的填充助手对象
            MimeMessageHelper helper = new MimeMessageHelper(msg, true);
            //设置主题
            helper.setSubject("测试带附件的邮件");
            //设置正文
            helper.setText("日出东方,唯我不败");
            //设置发件人
            helper.setFrom(mailProperties.getUsername());
            //设置发送日期
            helper.setSentDate(new Date());
            //设置收件人
            helper.setTo("mailTo");
            //添加附件  第一个是在别人邮箱里面的名字  第二个是自己的路径
            helper.addAttachment("liuyifei.jpg", new File("E:/liuyifei.jpg"));
            //发送
            javaMailSender.send(msg);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 使用模板发送邮件
     *
     * @param map
     * @param toAccount
     * @param subject
     * @param template
     */
    @Async
    public void sendHtmlTemplateMail(Map<String, Object> map, String toAccount, String subject, String template) {
        try {
            MimeMessage mimeMessage = javaMailSender.createMimeMessage();
            MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage);
            Context context = new Context();
            context.setVariables(map);
            String process = templateEngine.process(template, context);
            //设置发件人
            messageHelper.setFrom(mailProperties.getUsername());
            //设置收件人
            messageHelper.setTo(toAccount);
            //设置主题
            messageHelper.setSubject(subject);
            //设置内容，第二个参数 true 表示按照html来解析
            messageHelper.setText(process, true);
            javaMailSender.send(mimeMessage);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
